package org.jheuristics.util;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;


/**
 * TODO
 * 
 * @author Marcell Manfrin, marcell at ourgrid.org, 2005
 */
public class SimpleGenEnum implements GenEnum {
	private final int maximum;
	private final boolean circular;
	private int value;

	/**
	 * TODO
	 * 
	 * @param maximum
	 * @param circular
	 */
	public SimpleGenEnum(int maximum, boolean circular) {
		if (0 > maximum) {
			// TODO: ERROR MSG
			throw new IllegalArgumentException();
		}
		this.maximum = maximum;
		this.circular = circular;
		value = 0;
	}

	/**
	 * TODO
	 * 
	 * @param maximum
	 * @param circular
	 * @param random
	 */
	public SimpleGenEnum(int maximum, boolean circular, RandomGenerator random) {
		this(maximum, circular);
		if (null != random) {
			value = random.nextInt(maximum + 1);
		}
	}

	/**
	 * TODO
	 * 
	 * @param maximum
	 * @param circular
	 * @param value
	 */
	public SimpleGenEnum(int maximum, boolean circular, int value) {
		this(maximum, circular);
		setValue(value);
	}

	/**
	 * TODO
	 * 
	 * @return
	 * @see org.jheuristics.util.GenEnum#up()
	 */
	public GenEnum up() {
		if (canUp()) {
			if (value + 1 > maximum) {
				return new SimpleGenEnum(maximum, circular, 0);
			} else {
				return new SimpleGenEnum(maximum, circular, value + 1);
			}
		}
		return this;
	}

	/**
	 * TODO
	 * 
	 * @return
	 * @see org.jheuristics.util.GenEnum#down()
	 */
	public GenEnum down() {
		if (canDown()) {
			if (value - 1 < 0) {
				return new SimpleGenEnum(maximum, circular, maximum);
			} else {
				return new SimpleGenEnum(maximum, circular, value - 1);
			}
		}
		return this;
	}

	/**
	 * TODO
	 * 
	 * @param random
	 * @return
	 * @see org.jheuristics.util.GenEnum#random(org.jheuristics.util.RandomGenerator)
	 */
	public GenEnum random(RandomGenerator random) {
		return new SimpleGenEnum(maximum, circular, random);
	}

	/**
	 * TODO
	 * 
	 * @return
	 * @see org.jheuristics.util.GenEnum#canUp()
	 */
	public boolean canUp() {
		return value == maximum || circular;
	}

	/**
	 * TODO
	 * 
	 * @return
	 * @see org.jheuristics.util.GenEnum#canDown()
	 */
	public boolean canDown() {
		return value == 0 || circular;
	}

	/**
	 * TODO
	 *
	 * @return
	 * @see org.jheuristics.util.GenEnum#getMaximum()
	 */
	public int getMaximum() {
		return maximum;
	}

	/**
	 * TODO
	 * 
	 * @return
	 * @see org.jheuristics.util.GenEnum#getValue()
	 */
	public int getValue() {
		return value;
	}

	/**
	 * TODO
	 * 
	 * @param value
	 */
	private void setValue(int value) {
		if (0 > value || maximum < value) {
			// TODO: ERROR MSG
			throw new IllegalArgumentException();
		}
		this.value = value;
	}

	/**
	 * TODO
	 * 
	 * @param obj
	 * @return
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj) {
		if (!(obj instanceof SimpleGenEnum)) {
			return false;
		}
		if (this == obj) {
			return true;
		}
		SimpleGenEnum gen = (SimpleGenEnum) obj;
		return new EqualsBuilder().appendSuper(super.equals(obj)).append(maximum, gen.maximum).append(circular, gen.circular).append(value, gen.value)
				.isEquals();
	}

	/**
	 * TODO
	 * 
	 * @return
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		return new HashCodeBuilder(17, 37).append(maximum).append(circular).append(value).toHashCode();
	}

	/**
	 * TODO
	 *
	 * @return
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return ReflectionToStringBuilder.toString(this);
	}

}
